package com.kehutong.common.interceptor;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.coraframework.authz.exception.UnloginException;
import org.coraframework.inject.Inject;
import org.coraframework.inject.Singleton;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.HttpReqMsg;
import org.coraframework.mvc.http.interceptor.Exclude;
import org.coraframework.mvc.http.interceptor.Interceptor;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Entity;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.upload.FileItem;
import org.coraframework.util.Objects;

import com.alibaba.excel.exception.ExcelAnalysisException;
import com.kehutong.common.DoveClient;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.util.LogType;
import com.kehutong.common.util.Token;



/**
 * 系统拦截器
 * @author ThinkGem
 * @version 2013-6-6
 */
@Singleton
@Exclude({WebService.class, IgornLog.class})
public class LogInterceptor extends Interceptor {
	
	private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

	
	@Inject
	private JdbcSession jdbcSession;
	@Inject
	private DoveClient doveClient;
	
	@Override
	public Object intercept(HttpReqMsg req) throws Exception {
		Throwable ex = null;
		try {
			beforeInvoker(req);
			return req.invoke();

		} catch (ExcelAnalysisException e) {
			String exceptionMsg = e.getMessage();
			//excel头返回要求放在data里
			JSONObject errorJson = new JSONObject();
			errorJson.put("normalCount", 0);
			errorJson.put("errCount", 0);
			errorJson.put("successCount", 0);
			errorJson.put("errMsgs", exceptionMsg);
			return Result.error(0, "数据解析异常", errorJson);
		} catch (UnloginException e) {
			throw e;

		} catch (RuntimeException e) {
			logger.error(e);
			String exceptionMsg = e.getMessage();
			if(Objects.isBlank(exceptionMsg)){
				exceptionMsg = e.toString();
			}
			return Result.error(0,exceptionMsg);

		} catch (Throwable th) {
			throw new Exception(ex = th);

		} finally {
			afterInvoker(req, ex);
		}
	}
	
	private void beforeInvoker(HttpReqMsg req) {
		if (req.getActionPath() != null && !req.getActionPath().contains("login")) {
			String params = getParams(req.getParams());
			logger.info("params=" + params);
		}
	}
	
	private void afterInvoker(HttpReqMsg rq, Throwable ex) {
		try {
			Token token = getToken(rq.getBefore());
			if (Objects.isNull(token)) {
				return;
			}
			HttpServletRequest request = rq.getHttpServletRequest();
			String requestRri = request.getRequestURI();
			String uriPrefix = request.getContextPath();
			if ((requestRri.startsWith(uriPrefix) && 
					(requestRri.endsWith("/save") || 
							requestRri.endsWith("/delete") || 
							requestRri.endsWith("/import") || 
							requestRri.endsWith("/update") || 
							requestRri.endsWith("/updateSort"))) || 
					ex != null){
				
				
				doveClient.post("/admin/service/log/doLog", http->{
					http.addParam("companyNo", null2String(token.getCompanyNo()));
					http.addParam("companyName", null2String(token.getCompanyName()));
					http.addParam("type", (ex == null ? LogType.ACCESS : LogType.EXCEPTION).getId());
					http.addParam("remote_addr", null2String(getRemoteAddr(request)));
					http.addParam("user_agent", null2String(request.getHeader("user-agent")));
					http.addParam("request_uri", null2String(request.getRequestURI()));
					http.addParam("method", null2String(request.getMethod()));
					http.addParam("params", getParams(rq.getParams()));
					http.addParam("create_by", null2String(token.getUuid()));
					http.addParam("create_name", null2String(token.getUsername()));
					http.addParam("exception", null2String(ex));
				});
			}
		} catch (Exception e) {
			logger.error("log error:", e);

		}
//		logger.debug("最大内存: {}, 已分配内存: {}, 已分配内存中的剩余空间: {}, 最大可用内存: {}", 
//				Runtime.getRuntime().maxMemory(), Runtime.getRuntime().totalMemory(), Runtime.getRuntime().freeMemory(), 
//				Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory()); 
		
	}
	/**
     * 获得用户远程地址
     */
    private String getRemoteAddr(HttpServletRequest request){
        String remoteAddr = request.getHeader("X-Real-IP");
        if (Objects.nonEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("X-Forwarded-For");
        }
        if (Objects.nonEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("Proxy-Client-IP");
        }
        if (Objects.nonEmpty(remoteAddr)) {
            remoteAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
    }
    
    private String getParams(Object[] params) {
    	if (Objects.isEmpty(params)) {
    		return "";
    	}
    	
    	List<String> array = new ArrayList<>();
    	for (Object param : params) {
    		if (param == null) {
    			continue;
			}
    		if (param instanceof Token) {
    			continue;
    		} 
    		
    		if (param instanceof FileItem) {
    			continue;
    		}
    		
    		if (param instanceof Entity) {
    			return param.toString();
    		} 

    		if (param instanceof JSONObject) {
    			((JSONObject) param).remove("token");
    			return param.toString();
    		}
    		
    		array.add(param.toString());
    	}
    	
    	return String.join(", ", array);
    }
    
    private Token getToken(JSONObject jsonObject) {
    	if (Objects.isEmpty(jsonObject)) {
    		return null;
    	}
    	
    	return jsonObject.getObject("token", Token.class);
    }
    
    private String null2String(Object obj) {
    	if (obj == null) {
    		return "";
    	}
    	
    	return obj.toString();
    }

}
